package presentation.windowsFackData;

import java.awt.Dimension ;
import java.rmi.RemoteException ;
import java.util.Vector ;

import javax.swing.JButton ;
import javax.swing.JLabel ;
import javax.swing.JList ;
import javax.swing.JOptionPane ;
import javax.swing.JScrollPane ;
import javax.swing.JTextField ;
import javax.swing.ListModel ;
import javax.swing.ListSelectionModel ;
import javax.swing.SwingWorker ;

import presentation.UIDirectory ;
import presentation.UIThread ;
import presentation.models.SubDirsListCellRenderer ;
import presentation.models.SubDirsListModel ;
import presentation.models.ThreadsListCellRenderer ;
import presentation.models.ThreadsListModel ;
import presentation.windows.SharedUIData;
import util.Log ;
import util.NotFoundException ;
import util.Subsystem ;
import domain.user.Privilege ;
import domain.user.UnpermittedActionException ;



/**
* panel for viewing directory content with option to insert fake data.
* when created, presents the root directory content.
* when a sub-directory is chosen: refreshes presentation to present the sub-directory content.
* when a thread is chosen: the thread's content window pops up
*/
public class ViewDirectoryFakePanel extends BasePanelFake
{

	private static final long serialVersionUID = -2110755621658296959L ;

	private JList SubDirsList;
	private JList ThreadsList;
	private JButton viewThreadButton;
	private JScrollPane jScrollPane1;
	private JScrollPane jScrollPane2 ;
	private JButton deleteTopicButton;
	private JButton addThreadButton;
	private JTextField dirToAddTextField;
	private JButton addDirButton;
	private JLabel threadsLable;
	private JLabel subDirsLable;
	private JLabel dirNameLable;
	private JButton viewSubDirButton;

	/** the directory that its content is currently presented **/
	private UIDirectory presentedDirectory;



	/**
	 * construct ViewDirectoryPanel presenting the root directory
	 * @param sharedData - shared data to all panels, that is created once in the MainFrame
	 * @throws RemoteException if there was a communication problem
	 * @throws NotFoundException if the root directory was not found on the server
	 * (MainFrame should catch this exceptions and notify user)
	 */
	public ViewDirectoryFakePanel(final SharedUIData sharedData) throws RemoteException, NotFoundException
	{
		super(sharedData) ;
		this.setPreferredSize(new Dimension(735, 566));
		this.presentedDirectory = this.forum.getRootDirectory();
		this.initializeGUI();
		this.refreshPresentation();
		this.dirNameLable.setText("Main Directory");
	}


	/**
	 * add a new thread - from the AddTopicFrame
	 * @param topic the new topic to add
	 * @param message the message to add
	 * @throws RemoteException if a communication problem occurs
	 * @throws UnpermittedActionException if the action was unPermitted
	 * @throws NotFoundException if the current directory couldn't found
	 * all exceptions should be caught by AddTopicFrame
	 */
	public void addThread(final String topic, final String message) throws RemoteException, UnpermittedActionException, NotFoundException
	{
		long userId = this.getSharedData().getUser().getId();
		long containerDirectoryId = this.presentedDirectory.getId();
		UIThread thread = this.forum.addThread(containerDirectoryId, userId, topic, message);
		((ThreadsListModel)this.ThreadsList.getModel()).addElement(thread);
		this.ThreadsList.setSelectedValue(thread, true);
		Log.getLogger(Subsystem.PRESENTATION_MODEL).finest("user " + userId + " has added the thread "+topic+" with id "+thread.getId());
	}


	/**
	 * make this internal frame visible, and refresh it.
	 */
	@Override
	public void makeVisible(){
		try{
			this.refreshPresentation();
		}
		catch(Exception e){
			Log.getLogger(Subsystem.PRESENTATION_MODEL).info("could not refresh presentation for directory "+this.presentedDirectory.getId()) ;
		}
		super.makeVisible();

	}

	/**
	 * add sub-directory with the given name in the text field
	 */
	private void addDirButtonHandler()
	{
		new SwingWorker<Void,Void>(){

			@SuppressWarnings("synthetic-access")
			@Override
			protected Void doInBackground(){
				String dirName = ViewDirectoryFakePanel.this.dirToAddTextField.getText();
				if(dirName!=null && (!(dirName.equals(""))))
				{

					long userId = ViewDirectoryFakePanel.this.getSharedData().getUser().getId();
					long containerDirectoryId = ViewDirectoryFakePanel.this.presentedDirectory.getId();
					try
					{
						UIDirectory newAddedDir = ViewDirectoryFakePanel.this.forum.addDirectory(userId, containerDirectoryId, dirName);
						Log.getLogger(Subsystem.PRESENTATION_MODEL).finest("user " + userId + " has add directory "+dirName+" with id "+newAddedDir.getId());
						((SubDirsListModel)ViewDirectoryFakePanel.this.SubDirsList.getModel()).addElement(newAddedDir);
						ViewDirectoryFakePanel.this.SubDirsList.setSelectedValue(newAddedDir, true);
					}
					catch (RemoteException e)
					{
						Log.getLogger(Subsystem.PRESENTATION_MODEL).info("communication problem when trying to add sub directory.") ;
						//show error message:
						JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
							"problem with adding the directory", "error occured", JOptionPane.ERROR_MESSAGE);
					}
					catch (UnpermittedActionException e)
					{
						Log.getLogger(Subsystem.PRESENTATION_MODEL).info("user "+userId+" is unpermitted to add directory.") ;
						//show error message:
						JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
							"you are unpermitted to add directory", "error occured", JOptionPane.ERROR_MESSAGE);
					}
					catch (NotFoundException e)
					{
						Log.getLogger(Subsystem.PRESENTATION_MODEL).info("directory "+containerDirectoryId+" could not found.") ;
						//show error message:
						JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
							"problem with adding the directory", "error occured", JOptionPane.ERROR_MESSAGE);
					}
				}
				else{
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"enter directory name first!", "error occured", JOptionPane.ERROR_MESSAGE);
				}
				return null;
			}
			@SuppressWarnings("synthetic-access")
			@Override
			protected void done(){
				ViewDirectoryFakePanel.this.dirToAddTextField.setText("");
			}
		}.execute();
	}


	/**
	 * add thread by opening a new-topic window
	 */
	private void addThreadButtonHandler()
	{
		new SwingWorker<Void,Void>(){

			@Override
			protected Void doInBackground(){
				AddTopicFakeFrame addTopicFakeFrame = new AddTopicFakeFrame(ViewDirectoryFakePanel.this);
				addTopicFakeFrame.pack();
				ViewDirectoryFakePanel.this.addOpenSubFrame(addTopicFakeFrame);
				addTopicFakeFrame.setVisible(true);

				return null;
			}
			@Override
			protected void done() { /* there is nothing to do here .. */ }
		}.execute();
	}


	private void initializeGUI()
	{
		ListModel subDirsListModel = new SubDirsListModel();
		ListModel threadsListModel = new ThreadsListModel();

		this.SubDirsList = new JList();
		this.SubDirsList.setModel(subDirsListModel);
		this.SubDirsList.setCellRenderer(new SubDirsListCellRenderer());
		this.SubDirsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.SubDirsList.setSelectedIndex(0);
		this.SubDirsList.setBounds(30, 90, 619, 126);

		this.jScrollPane1 = new JScrollPane();
		this.add(this.jScrollPane1);
		this.jScrollPane1.setBounds(30, 90, 619, 126);
		this.jScrollPane1.setViewportView(this.SubDirsList);

		this.viewSubDirButton = new JButton();
		this.add(this.viewSubDirButton);
		this.viewSubDirButton.setText("View sub-directory");
		this.viewSubDirButton.setBounds(30, 228, 152, 24);

		this.dirNameLable = new JLabel();
		this.add(this.dirNameLable);
		this.dirNameLable.setBounds(240, 48, 383, 20);
		this.dirNameLable.setFont(new java.awt.Font("Californian FB",1,20));

		this.ThreadsList = new JList();
		this.ThreadsList.setModel(threadsListModel);
		this.ThreadsList.setCellRenderer(new ThreadsListCellRenderer());
		this.ThreadsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.ThreadsList.setSelectedIndex(0);
		this.ThreadsList.setBounds(30, 291, 619, 212);

		this.jScrollPane2 = new JScrollPane();
		this.add(this.jScrollPane2);
		this.jScrollPane2.setBounds(30, 291, 619, 212);
		this.jScrollPane2.setViewportView(this.ThreadsList);

		this.subDirsLable = new JLabel();
		this.add(this.subDirsLable);
		this.subDirsLable.setText("Sub directories:");
		this.subDirsLable.setBounds(35, 65, 116, 14);

		this.threadsLable = new JLabel();
		this.add(this.threadsLable);
		this.threadsLable.setText("Topics:");
		this.threadsLable.setBounds(30, 272, 43, 14);


		this.addDirButton = new JButton();
		this.add(this.addDirButton);
		this.addDirButton.setText("Add new Directory");
		this.addDirButton.setBounds(241, 229, 142, 21);

		this.dirToAddTextField = new JTextField();
		this.add(this.dirToAddTextField);
		this.dirToAddTextField.setBounds(407, 229, 242, 21);

		this.addThreadButton = new JButton();
		this.add(this.addThreadButton);
		this.addThreadButton.setText("Add new topic");
		this.addThreadButton.setBounds(251, 517, 183, 24);

		this.viewThreadButton = new JButton();
		this.add(this.viewThreadButton);
		this.viewThreadButton.setText("	View chosen topic");
		this.viewThreadButton.setBounds(30, 517, 158, 24);

		this.deleteTopicButton = new JButton();
		this.add(this.deleteTopicButton);
		this.deleteTopicButton.setText("delete chosen topic");
		this.deleteTopicButton.setBounds(491, 517, 158, 24);


		//show buttons only for privileged users:
		if(!this.getSharedData().getUser().isAllowed(Privilege.ADD_DIRECTORY))
		{
			this.addDirButton.setVisible(false);
			this.dirToAddTextField.setVisible(false);
		}

		if(!this.getSharedData().getUser().isAllowed(Privilege.ADD_THREAD))
		{
			this.addThreadButton.setVisible(false);
		}

		if(!this.getSharedData().getUser().isAllowed(Privilege.DELETE_THREAD))
		{
			this.deleteTopicButton.setVisible(false);
		}

		//set button handlers:
		this.viewSubDirButton.addActionListener(new java.awt.event.ActionListener() {
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt) {
	        	 ViewDirectoryFakePanel.this.viewSubDirButtonHandler();
	         }
		 });

		this.addDirButton.addActionListener(new java.awt.event.ActionListener() {
	         @SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt) {
	        	 ViewDirectoryFakePanel.this.addDirButtonHandler();
	         }
		 });

		this.viewThreadButton.addActionListener(new java.awt.event.ActionListener() {
	         @SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt) {
	        	 ViewDirectoryFakePanel.this.viewThreadButtonHandler();
	         }
		 });

		this.addThreadButton.addActionListener(new java.awt.event.ActionListener() {
	         @SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt) {
	        	 ViewDirectoryFakePanel.this.addThreadButtonHandler();
	         }
		 });


		this.deleteTopicButton.addActionListener(new java.awt.event.ActionListener() {
	         @SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt) {
	        	 ViewDirectoryFakePanel.this.removeThreadButtonHandler();
	         }
		 });
	}


	/**
	 * refresh the presented directory content
	 * @throws RemoteException when communication problem occurs
	 * @throws NotFoundException if the current directory was not found on the server
	 */
	private void refreshPresentation() throws RemoteException, NotFoundException{
		this.closeOpenSubFrames();
		long dirId = this.presentedDirectory.getId();

		Vector<UIDirectory> presentedSubDirectories = this.forum.getSubDirectories(dirId);
		Vector<UIThread> presentedThreads = this.forum.getThreads(dirId);

		((SubDirsListModel)this.SubDirsList.getModel()).setSubDirs(presentedSubDirectories);
		this.SubDirsList.setSelectedIndex(0);
		((ThreadsListModel)this.ThreadsList.getModel()).setThreads(presentedThreads);
		this.ThreadsList.setSelectedIndex(0);

		this.dirNameLable.setText("Directory: "+this.presentedDirectory.getName());

		//hide buttons from unPrivileged users:
		if(!this.getSharedData().getUser().isAllowed(Privilege.ADD_DIRECTORY))
		{
			this.addDirButton.setVisible(false);
			this.dirToAddTextField.setVisible(false);
		}

		if(!this.getSharedData().getUser().isAllowed(Privilege.ADD_THREAD))
		{
			this.addThreadButton.setVisible(false);
		}

		if(!this.getSharedData().getUser().isAllowed(Privilege.DELETE_THREAD))
		{
			this.deleteTopicButton.setVisible(false);
		}
	}

	/**
	 * add sub-directory with the given name in the text field
	 */
	private void removeThreadButtonHandler()
	{

		if(this.ThreadsList.getSelectedIndex() == -1)
		{
			//no selection
			JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
				"please choose topic to remove", "error occured", JOptionPane.ERROR_MESSAGE);
			return;
		}

		new SwingWorker<Void,Void>(){

			@SuppressWarnings("synthetic-access")
			@Override
			protected Void doInBackground(){

				UIThread chosenThread = (UIThread) ViewDirectoryFakePanel.this.ThreadsList.getSelectedValue();

				long userId = ViewDirectoryFakePanel.this.getSharedData().getUser().getId();
				long containerDirectoryId = ViewDirectoryFakePanel.this.presentedDirectory.getId();
				try
				{
					ViewDirectoryFakePanel.this.forum.deleteThread(userId, containerDirectoryId, chosenThread.getId());
					Log.getLogger(Subsystem.PRESENTATION_MODEL).finest("user " + userId + " has deleted the thread "+chosenThread.getTopic());
					((ThreadsListModel)ViewDirectoryFakePanel.this.ThreadsList.getModel()).removeElement(chosenThread);
				}
				catch (RemoteException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("communication problem when trying to remove thread.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"problem with removing the thread", "error occured", JOptionPane.ERROR_MESSAGE);
				}
				catch (UnpermittedActionException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("user "+userId+" is unpermitted to remove thread.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"you are unpermitted to remove topics", "error occured", JOptionPane.ERROR_MESSAGE);
				}
				catch (NotFoundException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("thread "+chosenThread.getId()+" could not found.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"problem with removing the thread", "error occured", JOptionPane.ERROR_MESSAGE);
					//try to recover by refreshing the content:
					try{
						ViewDirectoryFakePanel.this.refreshPresentation();
					}
					catch(Exception e2){
						Log.getLogger(Subsystem.PRESENTATION_MODEL).info("could not refresh presentation for directory "+ViewDirectoryFakePanel.this.presentedDirectory.getId()) ;
					}
				}
				return null;
			}
			@Override
			protected void done(){/*nothing to do here */}
		}.execute();
	}

	/**
	 * view a chosen sub directory by refreshing this panel:
	 */
	private void viewSubDirButtonHandler()
	{

		if(this.SubDirsList.getSelectedIndex() == -1)
		{
			//no selection
			JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
				"please choose directory to view", "error occured", JOptionPane.ERROR_MESSAGE);
			return;
		}

		//disable all buttons:
		this.viewThreadButton.setEnabled(false);
		this.deleteTopicButton.setEnabled(false);
		this.addThreadButton.setEnabled(false);
		this.addDirButton.setEnabled(false);
		this.viewSubDirButton.setEnabled(false);

		new SwingWorker<Void,Void>(){

			@SuppressWarnings("synthetic-access")
			@Override
			protected Void doInBackground(){
				UIDirectory chosenDir = (UIDirectory) ViewDirectoryFakePanel.this.SubDirsList.getSelectedValue();
				UIDirectory oldDir = ViewDirectoryFakePanel.this.presentedDirectory;
				ViewDirectoryFakePanel.this.presentedDirectory = chosenDir;
				try
				{
					ViewDirectoryFakePanel.this.refreshPresentation();
				}
				catch (RemoteException e)
				{

					ViewDirectoryFakePanel.this.presentedDirectory = oldDir;

					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("directory "+chosenDir.getId()+" could not found.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"problem with adding the directory", "error occured", JOptionPane.ERROR_MESSAGE);
				}
				catch (NotFoundException e)
				{
					ViewDirectoryFakePanel.this.presentedDirectory = oldDir;

					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("directory "+chosenDir.getId()+" could not found.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"problem with adding the directory", "error occured", JOptionPane.ERROR_MESSAGE);
					//try to recover by refreshing the content:
					try{
						ViewDirectoryFakePanel.this.refreshPresentation();
					}
					catch(Exception e2){
						Log.getLogger(Subsystem.PRESENTATION_MODEL).info("could not refresh presentation for directory "+ViewDirectoryFakePanel.this.presentedDirectory.getId()) ;
					}
				}
				return null;
			}
			@SuppressWarnings("synthetic-access")
			@Override
			protected void done(){
				//enable all buttons:
				ViewDirectoryFakePanel.this.viewThreadButton.setEnabled(true);
				ViewDirectoryFakePanel.this.deleteTopicButton.setEnabled(true);
				ViewDirectoryFakePanel.this.addThreadButton.setEnabled(true);
				ViewDirectoryFakePanel.this.addDirButton.setEnabled(true);
				ViewDirectoryFakePanel.this.viewSubDirButton.setEnabled(true);
			}
		}.execute();
	}

	/**
	 * view a chosen thread by creating a new pop up window:
	 */
	private void  viewThreadButtonHandler()
	{

		if(this.ThreadsList.getSelectedIndex() == -1)
		{
			//no selection
			JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
				"please choose topic to view", "error occured", JOptionPane.ERROR_MESSAGE);
			return;
		}


		new SwingWorker<Void,Void>(){
			@SuppressWarnings("synthetic-access")
			@Override
			protected Void doInBackground(){
				UIThread chosenThread = (UIThread) ViewDirectoryFakePanel.this.ThreadsList.getSelectedValue();

				//present the ViewThreadPanel as pop up window:
				try
				{
					ViewThreadFrameFakeWrapper frame = new ViewThreadFrameFakeWrapper(new ViewThreadFakePanel(ViewDirectoryFakePanel.this.getSharedData(), chosenThread));
					ViewDirectoryFakePanel.this.addOpenSubFrame(frame);
					frame.setVisible(true);
				}
				catch (RemoteException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("communication problem occured while trying to present a thread.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"cannot present the wanted thread at the moment", "error occured", JOptionPane.ERROR_MESSAGE);
				}
				catch (NotFoundException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("thread "+chosenThread .getId()+" could not found.") ;
					//show error message:
					JOptionPane.showMessageDialog(ViewDirectoryFakePanel.this,
						"cannot present the wanted thread at the moment", "error occured", JOptionPane.ERROR_MESSAGE);
					//try to recover by refreshing the content:
					try{
						ViewDirectoryFakePanel.this.refreshPresentation();
					}
					catch(Exception e2){
						Log.getLogger(Subsystem.PRESENTATION_MODEL).info("could not refresh presentation for directory "+ViewDirectoryFakePanel.this.presentedDirectory.getId()) ;
					}
				}
				return null;
			}
			@Override
			protected void done() { /* there is nothing to do here .. */ }
		}.execute();

	}





}

